home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / News / Alexandra.0.82 / Source / ColumnMatrix.m < prev    next >
Encoding:
Text File  |  1996-01-30  |  8.1 KB  |  411 lines

  1. #import "ColumnMatrix.h"
  2. #import "Article.h"
  3. #import "MatrixSet.h"
  4. #include <assert.h>
  5. #import "instr.h"
  6. #import "regexpr.h"
  7. #import "MatrixScroller.h"
  8.  
  9. @implementation ColumnMatrix
  10.  
  11. #define MOD(a,b) ((a)<0)? ((a)+(b))%(b) : (a)%(b)
  12.  
  13. - awakeFromNib
  14. {
  15.    buttonTitle=NXCopyStringBuffer([selectionButton title]);
  16.    return self;
  17. }
  18.  
  19. - free
  20. {
  21.    if(myVisibleCellList!=nil)
  22.       [myVisibleCellList free];
  23.    free(buttonTitle);
  24.    return [super free];
  25. }
  26.  
  27. - initFrame:(const NXRect *)frameRect
  28. {
  29.   NXSize newIntercell = {0.0, 0.0};
  30.   NXSize newCellSize;
  31.  
  32.   [super initFrame:frameRect mode:NX_LISTMODE prototype:[Cell new] numRows:0 numCols:0];
  33.   [protoCell setBordered:FALSE];
  34.   [protoCell setAlignment:NX_LEFTALIGNED];
  35.   
  36.   newCellSize.height=16.0;
  37.   newCellSize.width = frameRect->size.width;
  38.  
  39.   [self setCellSize:&newCellSize];
  40.   [self setIntercell:&newIntercell];
  41.   [self setBackgroundGray:NX_LTGRAY];
  42.   [self setAutoscroll:TRUE];
  43.  
  44.   return self;
  45. }
  46.  
  47. - superviewSizeChanged:(const NXSize*)oldSize
  48. {
  49.   NXSize    newCellSize;
  50.   NXRect aRect;
  51.  
  52.   [super superviewSizeChanged:oldSize];
  53.   
  54.   [superview getFrame:&aRect];
  55.   
  56.   newCellSize.width = aRect.size.width;
  57.   newCellSize.height = cellSize.height;
  58.   [self setCellSize:&newCellSize];
  59.   [self sizeToCells];
  60.   return self;
  61. }
  62.  
  63. - scrollUp
  64. {
  65.    NXSize visibleSize;
  66.    NXRect theUpperRect;
  67.  
  68.    [[[self superview] superview] getContentSize:&visibleSize];
  69.    NXSetRect(&theUpperRect,0.0,0.0,visibleSize.width,visibleSize.height);
  70.    [self scrollRectToVisible:&theUpperRect];
  71.  
  72.    return self;
  73. }
  74.    
  75. - loadMatrix
  76. {
  77.    int i,j;
  78.  
  79.    for(i=numRows-1;i>=0;i--)
  80.       [self removeRowAt:i andFree:NO];
  81.    [self makeVisibleCellList:self];
  82.    j=[myVisibleCellList count];
  83.    for(i=0;i<j;i++)
  84.       [self addRow];
  85.    [self sizeToCells];
  86.    [self clearSelectedCell];
  87.  
  88.    return self;
  89. }
  90.  
  91. - reloadMatrix
  92. {
  93.    List *selList;
  94.    int lastCellPos=NX_NOT_IN_LIST;
  95.    int i,j;
  96.  
  97.   selList=[self getSelectedCells:nil];
  98.   [self loadMatrix];
  99.   if(selList==nil)
  100.      return self;
  101.   j=[selList count];
  102.   for(i=0;i<j;i++){
  103.      id aCell=[selList objectAt:i];
  104.      if([aCell isTaged]==TRUE){
  105.         int pos=[cellList indexOf:aCell];
  106.         if(pos!=NX_NOT_IN_LIST){
  107.            [self setSelectionFrom:pos to:pos anchor:pos lit:YES];
  108.            lastCellPos=pos;
  109.         }
  110.      }    
  111.    }
  112.    [selList free];
  113.    if(lastCellPos!=NX_NOT_IN_LIST)
  114.       [self scrollCellToVisible:lastCellPos upperOffset:1.5 lowerOffset:1.5];
  115.   
  116.    return self;
  117. }
  118.  
  119. - setMatrixCellList:(List *)aList
  120. {
  121.    myCellList=aList;
  122.    return self;
  123. }
  124.  
  125. - makeVisibleCellList:sender
  126. {
  127.    int i,j;
  128.  
  129.    if(myVisibleCellList!=nil)
  130.       [myVisibleCellList free];
  131.    myVisibleCellList=[[List alloc] init];
  132.    j=[myCellList count];
  133.    for(i=0;i<j;i++){
  134.       id aCell=[myCellList objectAt:i];
  135.       if([aCell isTaged]==TRUE)
  136.          [myVisibleCellList addObject:aCell];
  137.    }
  138.    return self;
  139. }
  140.  
  141.  
  142. - makeCellAt:(int)row :(int)col
  143. {
  144.    assert(col==0);
  145.    return [myVisibleCellList objectAt:row];
  146. }
  147.  
  148. - (id)selectionButton
  149. {
  150.    return selectionButton;
  151. }
  152.  
  153. - removeInvalidCell:aCell
  154. {
  155.    return [self removeInvalidCell:aCell andUpdate:YES];
  156. }
  157.  
  158. - removeInvalidCell:aCell andUpdate:(BOOL)update
  159. {
  160.    int pos=[cellList indexOf:aCell];
  161.  
  162.    [myCellList removeObject:aCell];
  163.    [myVisibleCellList removeObject:aCell];
  164.    if(pos==NX_NOT_IN_LIST){
  165.       NX_ASSERT(pos==NX_NOT_IN_LIST,"Internal DS mismatch");
  166.       return self;
  167.    }
  168.    [self removeRowAt:pos andFree:YES];
  169.    if(update==YES)
  170.       [self update];
  171.    return self;
  172. }
  173.  
  174. - update
  175. {
  176.    [self reloadMatrix];
  177.    [self display];
  178.    [mySet sync];
  179.    [NXApp updateWindows];
  180.  
  181.    return self;
  182. }
  183.  
  184. - setButtonTitle:(const char *)title
  185. {
  186.    free(buttonTitle);
  187.    [selectionButton setTitle:title];
  188.    buttonTitle=NXCopyStringBuffer(title);
  189.  
  190.    return self;
  191. }
  192.  
  193. - _delayedUpdate:sender
  194. {
  195.    [selectionButton setTitle:buttonTitle];
  196.    return self;
  197. }
  198.  
  199. - updateButtonTitle
  200. {
  201.    [self perform:@selector(_delayedUpdate:) with:self afterDelay:0.0 cancelPrevious:TRUE];  
  202.    return self;
  203. }
  204.  
  205. - (List *)getCurrSelections
  206. {
  207.    return [self getSelectedCells:nil];
  208. }
  209.  
  210. - currSelection
  211. {
  212.    return [self selectedCell];
  213. }
  214.  
  215. - (BOOL)selectNextCell:(int)delta
  216. {
  217.     int i,j;
  218.     id cSel;
  219.  
  220.     NX_ASSERT(((delta==1) || (delta==-1)),"Wrong parameter selectNextCell");
  221.     
  222.     j=[myVisibleCellList count];
  223.     if(j==0)
  224.        return FALSE;
  225.  
  226.     if((cSel=[mySet currentSelection])!=nil){
  227.         i=[myVisibleCellList indexOf:cSel];
  228.         NX_ASSERT(i!=NX_NOT_IN_LIST,"Internal DS mismatch");
  229.         if((delta>0) && (i==j-1))
  230.            return FALSE; //last article
  231.         else
  232.           if((delta<0) && (i==0))
  233.              return FALSE; //first article
  234.     }
  235.     else
  236.        if(delta>0)
  237.           i=-1;
  238.        else
  239.           i=j;
  240.  
  241.    [self selectCellAt:i+delta :0];
  242.    [self scrollCellToVisible:i+delta upperOffset:((delta==-1)? 1.5:0.0) lowerOffset:((delta==1)? 1.5:0.0)];
  243.    [self sendAction];
  244.  
  245.    return TRUE;
  246. }
  247.  
  248. - selectAll:sender
  249. {
  250.  
  251.    [super selectAll:sender];
  252.    [self sendAction];
  253.  
  254.    return self;
  255. }
  256.  
  257. - mySet
  258. {
  259.    return mySet;
  260. }
  261.  
  262. //-------------------------
  263. // searchable text protocol
  264. //-------------------------
  265.  
  266. - (oneway void)makeSelectionVisible
  267. {
  268.    id selCell=[self selectedCell];
  269.  
  270.    if(selCell!=nil)
  271.       [self scrollCellToVisible:[[self cellList] indexOf:selCell] 
  272.             upperOffset:(findNext? 0.0:1.5) lowerOffset:(findNext? 1.5:0.0)];
  273. }
  274.  
  275. - (int)replaceAll:(const char *)pattern with:(const char *)replacement mode:(SearchMode)mode regexpr:(BOOL)regexpr cases:(BOOL)cases
  276. {
  277.    return SEARCH_CANNOT_WRITE;
  278. }
  279.  
  280. - (oneway void)replaceSelection:(const char *)replacement
  281. {
  282. }
  283.  
  284. - (const char *)stringValueForCellAt:(int)index
  285. {
  286.    return [[self cellAt:index :0] stringValue];
  287. }
  288.  
  289. - (int)searchFor:(const char *)pattern mode:(SearchMode)mode reverse:(BOOL)rev regexpr:(BOOL)regexpr cases:(BOOL)cases position:(out int *)pos size:(out int *)size
  290. {
  291.    int rows,cols,i;
  292.    int s_pos;
  293.    int fStart,fEnd;
  294.    int delta;
  295.  
  296.    unsigned char fm[256], tr[256];
  297.    struct re_pattern_buffer rpat;
  298.  
  299.    findNext=!rev;
  300.  
  301.    s_pos=-2;
  302.    fStart=fEnd=-2;
  303.  
  304.    [self getNumRows:&rows numCols:&cols];
  305.    if(rows==0)
  306.       return 0;
  307.  
  308.    // find first selected cell
  309.    for(i=0;i<rows;i++)
  310.       if([[self cellAt:i :0] state]){
  311.          s_pos=i;
  312.          break;
  313.       }
  314.  
  315.    if(!rev){
  316.       if(s_pos<0){ 
  317.          fStart=0; fEnd=rows; 
  318.       }
  319.       else{
  320.          fStart=s_pos+1; fEnd=s_pos+rows; 
  321.       }
  322.    }
  323.    else{
  324.       if(s_pos<0){ 
  325.          fStart=rows-1; fEnd=-1; 
  326.       }
  327.       else{
  328.          fStart=s_pos-1+rows; fEnd=s_pos; 
  329.       }
  330.    }
  331.    
  332.    delta= rev? -1:1;
  333.   
  334.    if(regexpr){
  335.       char *str;
  336.       int i;
  337.  
  338.       memset(&rpat, 0, sizeof(rpat));
  339.       for(i=256; i--;)
  340.          tr[i] = i;
  341.       if(!cases)
  342.          for(i='A'; i<='Z'; i++)
  343.             tr[i] = i-'A'+'a';
  344.       rpat.translate = tr;
  345.       rpat.fastmap = fm;
  346.       str = re_compile_pattern((char *)pattern,strlen(pattern), &rpat);
  347.       if (str!=NULL)
  348.         return (strcmp(str, "Out of memory")?SEARCH_INVALID_REGEXPR:SEARCH_INTERNAL_ERROR);
  349.    }
  350.  
  351.    for(;fStart!=fEnd;fStart+=delta){
  352.       int index=fStart%rows;
  353.       const char *result=NULL;
  354.       const char *cellString=[self stringValueForCellAt:index];
  355.  
  356.       if(regexpr){
  357.         int l=strlen(cellString);
  358.         int p=re_search_pattern(&rpat,(char *)cellString,l,0,l,0);
  359.  
  360.         if(p==-2)
  361.            return SEARCH_INTERNAL_ERROR;
  362.         result= (p==-1)? NULL : cellString;
  363.       }
  364.       else
  365.          result=instr(cellString,pattern,cases);
  366.  
  367.       if(result!=NULL){
  368.          *pos=index;
  369.          *size=1;
  370.          return 1;
  371.       }
  372.    }
  373.    
  374.    return 0;
  375. }
  376.  
  377. - (oneway void)selectTextFrom:(int)start to:(int)end
  378. {
  379.    int rows,cols;
  380.    if(start<=end){
  381.       if(start==end){
  382.          [self selectCellAt:-1 :-1];
  383.          [self sendAction];
  384.       }
  385.       else{
  386.          [self getNumRows:&rows numCols:&cols];
  387.          if(end<=rows){
  388.             [self selectCellAt:start :0];
  389.             [self sendAction];
  390.          }
  391.       }
  392.    }
  393. }
  394.       
  395. - (void)writeSelectionToPasteboard:(in Pasteboard *)pboard asType:(in NXAtom)type
  396. {
  397.     id aList =[self getCurrSelections];
  398.     
  399.    
  400.    if([aList count]==1){
  401.       const char *sval=[[aList objectAt:0] stringValue];
  402.       [pboard declareTypes:&type num:1 owner:NULL];
  403.       [pboard writeType:type data:sval length:strlen(sval)];
  404.    }
  405.     [aList free];
  406.     
  407.    return;
  408. }
  409.  
  410. @end
  411.